/*
 * Copyright (c) 2022 Agustina Arzille.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include <string.h>
#include <kern/fmt.h>
#include <kern/init.h>
#include <kern/log.h>
#include <test/test.h>

struct test_stream
{
  struct stream base;
  char *buf;
  uint32_t len;
};

static void
test_stream_write (struct stream *stream, const void *data, uint32_t bytes)
{
  _Auto sp = (struct test_stream *) stream;
  for (uint32_t i = 0; i < bytes; ++i)
    {
      int ch = ((const char *)data)[i];
      sp->buf[sp->len + i] = ch < 'A' || ch > 'Z' ? ch : ((ch - 'A') + 'a');
    }

  sp->len += bytes;
}

static const struct stream_ops test_stream_ops =
{
  .write = test_stream_write
};

static void
test_sscanf (void)
{
  int x1, x2;
  char c1, c2;

  int rv = fmt_sscanf ("123 qx -45", "%d %c%c %d", &x1, &c1, &c2, &x2);
  test_assert_eq (rv, 4);
  test_assert_eq (x1, 123);
  test_assert_eq (c1, 'q');
  test_assert_eq (c2, 'x');
  test_assert_eq (x2, -45);
}

TEST_INLINE (fmt)
{
  char buf[32];
  int rv = fmt_sprintf (buf, "hello %d %s", -4, "???");
  test_assert_eq (rv, 12);
  test_assert_streq (buf, "hello -4 ???");

  rv = fmt_snprintf (buf, 4, "abc%d", 33);
  test_assert_eq (rv, 5);
  buf[rv - 1] = '\0';
  test_assert_streq (buf, "abc3");

  struct test_stream stream = { .buf = buf, .len = 0 };
  stream_init (&stream.base, &test_stream_ops);

  rv = fmt_xprintf (&stream.base, "HELLO %d", -1);
  test_assert_gt (rv, 0);
  buf[rv] = '\0';
  test_assert_streq (buf, "hello -1");

  test_sscanf ();
  return (TEST_OK);
}
